MODULE TuringPll;

IMPORT
	Raster, Random, Objects, WMRectangles, WMGraphics, Modules, Strings,
	WM := WMWindowManager;

CONST
	M = 150; 
	SIZE = 2;

TYPE Twindow* =  OBJECT(WM.BufferWindow)
VAR
	mesh1, mesh2, n1 : ARRAY M,M OF REAL;
	alive, dead: BOOLEAN;
	i : LONGINT;
		
PROCEDURE KeyEvent (ucs : LONGINT; flags : SET; keysym : LONGINT);
BEGIN
	CASE CHR(ucs) OF
		| 'q': Close
	ELSE
	END
END KeyEvent;

PROCEDURE &New*;
VAR 
	i, j : LONGINT;
BEGIN
	Init(M*SIZE, M*SIZE, FALSE);
	manager := WM.GetDefaultManager();
	manager.Add(100, 100, SELF, {WM.FlagFrame, WM.FlagClose, WM.FlagNoResizing});
	SetTitle(Strings.NewString("TuringPll Tutorial For Lac"));
	SetIcon(WMGraphics.LoadImage("WMIcons.tar://TuringCoatWnd.png", TRUE));
	FOR i := 0 TO M - 1 DO
		FOR j := 0 TO M - 1 DO
			mesh1[i, j] := 0;
			mesh2[i, j] := 0;
			n1[i, j] := 0
		END
	END;
	FOR i :=  1 TO M - 2 DO
		FOR j := 1 TO M - 2 DO
			IF random.Dice(100) > 90 THEN mesh1[i, j] := random.Dice(1000)/1000 END
		END
	END;
END New;

PROCEDURE Draw*(canvas : WMGraphics.Canvas; w, h, q : LONGINT);
BEGIN
	Draw^(canvas, w, h, 0)
END Draw;

PROCEDURE Close;
BEGIN
	alive := FALSE;
	BEGIN {EXCLUSIVE} AWAIT(dead); END;
	Close^;
END Close;

PROCEDURE Generation;
VAR i, j : LONGINT;
BEGIN
	FOR i := 1 TO M - 2 DO
		n1[i, 0] := mesh1[i - 1, 0] + mesh1[i + 1, 0] + mesh1[i, M - 1] + mesh1[i, 1]
		 	+ mesh1[i - 1, M - 1] +  mesh1[i + 1, 1] + mesh1[i + 1, M - 1] + mesh1[i - 1,  1];
		n1[i, M - 1] := mesh1[i - 1, M - 1] + mesh1[i + 1, M - 1] + mesh1[i, M - 2] + mesh1[i, 0]
			+ mesh1[i - 1, M - 2] +  mesh1[i + 1, 0] + mesh1[i + 1, M - 2] + mesh1[i - 1, 0];
		END;
	FOR j := 1 TO M - 2 DO
		n1[0, j] := mesh1[M - 1, j] + mesh1[1, j] + mesh1[0, j - 1] + mesh1[0, j + 1]
			+ mesh1[M - 1, j - 1] +  mesh1[1, j + 1] + mesh1[1, j - 1] + mesh1[M - 1, j + 1];
		n1[M - 1, j] := mesh1[M - 2, j] + mesh1[0, j] + mesh1[M - 1, j - 1] + mesh1[M - 1, j + 1]
			+ mesh1[M - 2, j - 1] +  mesh1[0, j + 1] + mesh1[0, j - 1] + mesh1[M - 2, j + 1]
	END;
	FOR i := 1 TO M - 2 DO
		FOR j := 1 TO M - 2 DO
			n1[i, j] := mesh1[i - 1, j] + mesh1[i + 1, j] + mesh1[i, j - 1] + mesh1[i, j + 1]
				+ mesh1[i - 1, j - 1] +  mesh1[i + 1, j + 1] + mesh1[i + 1, j - 1] + mesh1[i - 1, j + 1]
		END
	END;
	FOR i := 1 TO M - 2 DO
		FOR j := 1 TO M - 2 DO
			(*  HERE ARE THE DIFFERENCE RULES! *)
			mesh1[i, j] := mesh1[i, j] + n1[i, j] / 80- (mesh2[i, j] * mesh2[i, j])  ;
			mesh2[i, j] := mesh2[i, j] +  mesh1[i, j] / 20 - 0.03 ;
			IF mesh1[i, j] < 0 THEN mesh1[i, j] := 0 END;
			IF mesh2[i, j] < 0 THEN mesh2[i, j] := 0 END;
			IF mesh1[i, j] > 1 THEN mesh1[i, j] := 1 END;
			IF mesh2[i, j] > 1 THEN mesh2[i, j] := 1 END;
		END;
	END;
END Generation;

PROCEDURE DrawIt;
VAR i, j, ix, jy : LONGINT;
	pix : Raster.Pixel;
	mode : Raster.Mode;
BEGIN
	Raster.InitMode(mode, Raster.srcCopy);
	FOR i := 0 TO M - 1 DO
		ix := i * SIZE;
		FOR j := 0 TO M - 1 DO
			jy := j * SIZE;
			Raster.SetRGB(pix, SHORT((255-ENTIER(mesh1[i, j] * 255)) ), SHORT((255-ENTIER(mesh2[i, j] * 255)) ), 0);
			Raster.Fill(img, ix, jy, ix+SIZE, jy+SIZE, pix, mode)
		END
	END;
	Invalidate(WMRectangles.MakeRect(0, 0, GetWidth(), GetHeight()))
END DrawIt;

BEGIN {ACTIVE}
	alive := TRUE;
	Objects.SetPriority(Objects.Low);
	WHILE alive DO
		FOR i := 0 TO 0 DO Generation END;
			DrawIt;
		END;
	BEGIN {EXCLUSIVE} dead := TRUE; END;
END Twindow;

VAR
	tw: Twindow;
	random : Random.Generator;
	
PROCEDURE Open*;
BEGIN
	NEW(tw);
END Open;

PROCEDURE Close*;
BEGIN
	IF tw#NIL THEN tw.Close; tw:=NIL END;
END Close;

BEGIN
	Modules.InstallTermHandler(Close);
	NEW(random);
END TuringPll.

SystemTools.Free TuringPll ~

TuringPll.Open ~
